<?php
/**
 * Created by PhpStorm.
 * User: Guo
 * Date: 2017/7/16
 * Time: 23:22
 */

namespace app\api\service;


use app\lib\enum\ScopeEnum;
use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\common\model\User as UserModel;

class UserToken extends Token
{
    protected $code;
    protected $wxAppId;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    public function __construct($code)
    {
        $this->code = $code;
        $this->wxAppId = config('wx.app_id');
        $this->wxAppSecret = config('wx.app_secret');
        $this->wxLoginUrl = sprintf(config('wx.login_url'), $this->wxAppId, $this->wxAppSecret, $this->code);
    }

    public function get()
    {
        $result = curl_get($this->wxLoginUrl);
        $wxResult = json_decode($result, true);
        if (empty($wxResult)) {
            throw new Exception('获取session key及open_ID时异常，微信内部错误');
        } else {
            $loginFail = array_key_exists('errcode', $wxResult);
            if ($loginFail) {
                $this->processLoginError($wxResult);
            } else {
                return $this->grantToken($wxResult);
            }
        }
    }

    private function grantToken($wxResult)
    {
        // 拿到openid
        // 数据库里看一下，这个openid是不是已经存在
        // 如果存在，则不处理，如果不存在那么新增一条user记录
        // 生成令牌，准备缓存数据，写入缓存
        // 把令牌返回到客户端去
        // key: 令牌
        // value: wxResult ukd scope
        $openid = $wxResult['openid'];
        $user = UserModel::getByOpenId($openid);
        if ($user) {
            $uid = $user->id;
        } else {
            $uid = $this->newUser($openid);
        }
        $cachedValue = $this->prepareCachedValue($wxResult, $uid);
        $token = $this->saveToCache($cachedValue);
        return [
            'uid'   =>  $uid,
            'token' =>  $token
        ];
    }

    private function saveToCache($cachedValue)
    {
        $key        = self::generateToken();
        $value      = json_encode($cachedValue);
        $expire_in  = config('setting.token_expire_in');
        $request    = cache($key, $value, $expire_in);
        if (!$request) {
            throw new TokenException([
                'msg'       => '服务器缓存异常',
                'errorCode' =>  10005
            ]);
        }
        return $key;
    }

    private function prepareCachedValue($wxResult, $uid)
    {
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
        // scope = 16 代表APP用户的权限数值
        $cachedValue['scope'] = ScopeEnum::User;
        // scope = 32 代表CMS用户（管理员）用户的权限数值
        //$cachedValue['scope'] = ScopeEnum::Super;
        return $cachedValue;
    }

    private function newUser($openid)
    {
        $user = UserModel::create([
            'openid'    =>  $openid
        ]);
        return $user->id;
    }

    private function processLoginError($wxResult)
    {
        throw new WeChatException([
            'msg'       =>  $wxResult['errmsg'],
            'errorCode' =>  $wxResult['errcode']
        ]);

    }

    public function getOpenId()
    {
        $result = curl_get($this->wxLoginUrl);
        $wxResult = json_decode($result, true);
        return $wxResult['openid'];
    }

}